package com.sie.framework.plugin.printer;

import java.lang.reflect.Method;
import java.util.Hashtable;
import java.util.Iterator;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import com.bankcomm.peripheral.PeripheralCallback;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.printer.sdk.Barcode;
import com.printer.sdk.PrinterConstants.BarcodeType;
import com.printer.sdk.PrinterConstants.Command;
import com.printer.sdk.PrinterConstants.Connect;
import com.printer.sdk.PrinterConstants.LableFontSize;
import com.printer.sdk.PrinterConstants.PAlign;
import com.printer.sdk.PrinterConstants.PRotate;
import com.printer.sdk.PrinterInstance;
import com.sie.framework.constconfig.ErrorDefine;
import com.sie.tools.LogUtil;

public class BluetoothOperation implements IPrinterOpertion {
	private static final String TAG = "BluetoothOpertion";
	private BluetoothAdapter adapter;
	private Context mContext;
	private boolean hasRegBoundReceiver;
	private boolean rePair;

	private BluetoothDevice mDevice;
	private String deviceAddress;

	public PrinterInstance mPrinter;
	private boolean hasRegDisconnectReceiver;
	private IntentFilter filter;
	public static String EXTRA_DEVICE_ADDRESS = "device_address";
	public static String EXTRA_RE_PAIR = "re_pair";

	public PeripheralCallback callback;

	public void setCallback() {

	}

	@SuppressLint("HandlerLeak")
	private Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			
			case Connect.SUCCESS: {
				LogUtil.mLog("打印机连接状态SUCCESS：" + mPrinter.getCurrentStatus());
				if (callback != null)
					callback.onSuccess(new Bundle());
				break;
			}
			case Connect.FAILED: {
				LogUtil.mLog("打印机连接状态FAILED：" + mPrinter.getCurrentStatus());
				if (callback != null)
					callback.onFail(new Bundle());
				break;
			}
			case Connect.CLOSED: {
				LogUtil.mLog("打印机连接状态CLOSED：" + mPrinter.getCurrentStatus());
				Log.e("tag","是不是这里报close");
				if (callback != null)
					callback.onFail(new Bundle());
				break;
			}
			}

		}
	};

	public BluetoothOperation(PeripheralCallback callback) {
		adapter = BluetoothAdapter.getDefaultAdapter();
		hasRegDisconnectReceiver = false;
		this.callback =callback;
		filter = new IntentFilter();
		filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
	}

	@Override
	public void open(BluetoothDevice mDevice) {
		
		this.deviceAddress = mDevice.getAddress();
		this.mDevice = adapter.getRemoteDevice(deviceAddress);
		if (mDevice.getBondState() == BluetoothDevice.BOND_NONE) {
			Log.i(TAG, "device.getBondState() is BluetoothDevice.BOND_NONE");
			PairOrRePairDevice(false, mDevice);
		} else if (mDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
			rePair = false;
			if (rePair) {
				PairOrRePairDevice(true, mDevice);
			} else {
				openPrinter();
			}
		}
	}

	// use device to init printer.
	public void openPrinter() {
		
		if(mPrinter!=null){
			
			mPrinter.closeConnection();
			
			
		}
		mPrinter = PrinterInstance.getPrinterInstance(mDevice, mHandler);
		mPrinter.openConnection();

	}

	private boolean PairOrRePairDevice(boolean re_pair, BluetoothDevice device) {
		boolean success = false;
		try {
			if (!hasRegBoundReceiver) {
				mDevice = device;
				IntentFilter boundFilter = new IntentFilter(
						BluetoothDevice.ACTION_BOND_STATE_CHANGED);
				mContext.registerReceiver(boundDeviceReceiver, boundFilter);
				hasRegBoundReceiver = true;
			}

			if (re_pair) {
				// cancel bond
				Method removeBondMethod = BluetoothDevice.class
						.getMethod("removeBond");
				success = (Boolean) removeBondMethod.invoke(device);
				Log.i(TAG, "removeBond is success? : " + success);
			} else {
				Method createBondMethod = BluetoothDevice.class
						.getMethod("createBond");
				success = (Boolean) createBondMethod.invoke(device);
				Log.i(TAG, "createBond is success? : " + success);
			}
		} catch (Exception e) {
			Log.i(TAG, "removeBond or createBond failed.");
			e.printStackTrace();
			success = false;
		}
		return success;
	}

	// receive bound broadcast to open connect.
	private BroadcastReceiver boundDeviceReceiver = new BroadcastReceiver() {
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
				BluetoothDevice device = intent
						.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
				if (!mDevice.equals(device)) {
					return;
				}
				switch (device.getBondState()) {
				case BluetoothDevice.BOND_BONDING:
					Log.i(TAG, "bounding......");
					break;
				case BluetoothDevice.BOND_BONDED:
					Log.i(TAG, "bound success");
					// if bound success, auto init BluetoothPrinter. open
					// connect.
					if (hasRegBoundReceiver) {
						mContext.unregisterReceiver(boundDeviceReceiver);
						hasRegBoundReceiver = false;
					}
					openPrinter();
					break;
				case BluetoothDevice.BOND_NONE:
					if (rePair) {
						rePair = false;
						Log.i(TAG, "removeBond success, wait create bound.");
						PairOrRePairDevice(false, device);
					} else if (hasRegBoundReceiver) {
						mContext.unregisterReceiver(boundDeviceReceiver);
						hasRegBoundReceiver = false;
						// bond failed
						mHandler.obtainMessage(Connect.FAILED).sendToTarget();
						Log.i(TAG, "bound cancel");
					}
				default:
					break;
				}
			}
		}
	};

	//打印机状态 0.已连接  1.断开连接  
	public static int getPrinterStatus(PeripheralCallback callback){
			
			Bundle bundle = new Bundle();
			if (PrinterInstance.mPrinter != null){
				int code = PrinterInstance.mPrinter.getCurrentStatus();
				LogUtil.mLog("sdk getCurrentStatus:"+code);
				switch (code) {
				case 0:
					bundle.putString("code", ""+ErrorDefine.ERR_PRINTER_HAS_CONNECTED);
					bundle.putString("message", "打印机已连接");
					if (callback!= null) callback.onSuccess(bundle);
					return ErrorDefine.ERR_PRINTER_HAS_CONNECTED;
				case -1:
					bundle.putString("code", ""+ErrorDefine.ERR_PRINTER_HAS_CONNECTED);
					bundle.putString("message", "打印机已连接");
					if (callback!= null) callback.onSuccess(bundle);
					return ErrorDefine.ERR_PRINTER_HAS_CONNECTED;
				case -2: //
					bundle.putString("code", ""+ErrorDefine.ERR_PRINTER_HAS_DISCONNECTED);
					bundle.putString("message", "打印机断开连接");
					if (callback!= null) callback.onFail(bundle);
					return ErrorDefine.ERR_PRINTER_HAS_DISCONNECTED;
				default:
					bundle.putString("code", ""+ErrorDefine.ERR_PRINTER_HAS_DISCONNECTED);
					bundle.putString("message", "打印机断开连接");
					if (callback!= null) callback.onFail(bundle);
					return ErrorDefine.ERR_PRINTER_HAS_DISCONNECTED;
				}
							
			}else{
				bundle.putString("code", ""+ErrorDefine.ERR_PRINTER_HAS_DISCONNECTED);
				bundle.putString("message", "打印机断开连接");
				if (callback!= null) callback.onFail(bundle);
				return ErrorDefine.ERR_PRINTER_HAS_DISCONNECTED;
			}
		}
	
	public void printDataString(final String data,
			final PeripheralCallback callback) {
		// TODO Auto-generated method stub
		new Thread(new Runnable() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				JSONObject objJson = null;
				try {
					objJson = new JSONObject(data);
				} catch (JSONException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				try {
					if (analysisJson(objJson)) {

						callback.onSuccess(new Bundle());

					} else {
						Bundle bundle = new Bundle();
						bundle.putString("code", ErrorDefine.ERR_PRINTER_CONNECT_FAIL+"");
						bundle.putString("message", "连接打印机失败");
						callback.onFail(bundle);
					}
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					Bundle bundle = new Bundle();
					bundle.putString("code", ErrorDefine.ERR_PRINTER_DATA_PARSE_FAIL+"");
					bundle.putString("message", "打印数据解析错误");
					callback.onFail(bundle);
				}

			}
		}).start();

	}
	
	public void close() {
		if (mPrinter != null) {
			mPrinter.closeConnection();
			mPrinter = null;
		}
		if (hasRegDisconnectReceiver) {
			mContext.unregisterReceiver(myReceiver);
			hasRegDisconnectReceiver = false;
		}
	}

	public PrinterInstance getPrinter() {
		if (mPrinter != null) {
			if (!hasRegDisconnectReceiver) {
				mContext.registerReceiver(myReceiver, filter);
				hasRegDisconnectReceiver = true;
			}
		}
		return mPrinter;
	}

	// receive the state change of the bluetooth.
	private BroadcastReceiver myReceiver = new BroadcastReceiver() {
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			BluetoothDevice device = intent
					.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

			Log.i(TAG, "receiver is: " + action);
			if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
				if (device != null && mPrinter != null
						&& device.equals(mDevice)) {
					LogUtil.mLog( "打印机连接状态：" + mPrinter.getCurrentStatus());
					close();
				}
			}
		}
	};

	public boolean analysisJson(Object objJson) throws JSONException {
		
			Log.e("", "Object==="+objJson);
			JSONObject jsonObject = (JSONObject) objJson;
			Log.e("", "jsonObject==="+jsonObject.toString());
			@SuppressWarnings("rawtypes")
			Iterator it = jsonObject.keys();
			mPrinter.initPrinter();
			while (it.hasNext()) {
				// 最外层循环 解析打印类型
				String key = it.next().toString();
				Log.e("key:", key);
				JSONArray array = (JSONArray) jsonObject.get(key);
				for (int i = 0; i < array.length(); i++) {

					// 内层循环解析打印设置
					JSONObject item = (JSONObject) array.get(i);
					if (key.equalsIgnoreCase("bitmap")) {
						float scale = 1;
						if (item.opt("percent") != null) {
							String percent = item.getString("percent");
							scale = Float.valueOf(percent);
						}
						Bitmap bitmap = null;
						
						if (!TextUtils.isEmpty(item.optString("path"))) {

							String itemVal = item.getString("path");
							Log.e("", "path==="+itemVal);
							Bitmap tmpBmp = ImageUnit.GetLocalOrNetBitmap(itemVal);
							if(tmpBmp==null){
								continue;
							}
							bitmap = tmpBmp;/*ImageUnit.binarization(tmpBmp,
									(int) (tmpBmp.getWidth() * scale),
									(int) (tmpBmp.getHeight() * scale));*/
						}
						if(bitmap==null){
							continue;
						}
						if (item.opt("content") != null) {
							String itemVal = item.getString("content");
							Bitmap tmpBmp = ImageUnit.base64ToBitmap(itemVal);
							bitmap = ImageUnit.binarization(tmpBmp,
									(int) (tmpBmp.getWidth() * scale),
									(int) (tmpBmp.getHeight() * scale));

						}

						if (item.opt("alignment") != null) {
							String itemVal = item.getString("alignment");
							Log.e("alignment", itemVal);
							if (itemVal.equals("left")) {
								 mPrinter.printImage(bitmap,PAlign.START, 0, false);
							}
							if (itemVal.equals("middle")) {

	                            mPrinter.printImage(bitmap,PAlign.CENTER, 0, false);
							}
							if (itemVal.equals("right")) {
							
								 mPrinter.printImage(bitmap,PAlign.END, 0, false);
							}
						} else {
							 mPrinter.printImage(bitmap,PAlign.NONE, 0, false);

						}

					}

					if (key.equalsIgnoreCase("string")) {
						String content = null;
						int xsize = 0;
						int ysize = 0;
						boolean isBold = false;
						boolean isUnderLine = false;
						PRotate pr = PRotate.Rotate_0;
						String xoffset = "";
						LableFontSize size = LableFontSize.Size_16;

						if (item.opt("content") != null) {
							content = item.getString("content");
						}
						Log.e("print", "string:" + content);

						if (item.opt("xsize") != null) {
							xsize = (int) item.getDouble("xsize");
							
						}
						if (item.opt("ysize") != null) {
							ysize = (int) item.getDouble("ysize");
						
						}

						if (item.opt("bold") != null) {
							isBold = item.getBoolean("bold");
						}
						if (item.opt("underline") != null) {
							isUnderLine = item.getBoolean("underline");
						}

						if (item.opt("alignment") != null) {
							String itemVal = item.getString("alignment");
							if (itemVal.equals("left")) {

								
								
							}
							if (itemVal.equals("middle")) {
								
								
								
							}
							if (itemVal.equals("right")) {

								
								
							}
						}
						if (item.opt("angle") != null) {
							int  itemVal = item.getInt("angle");
							if(itemVal == 90){
								pr = PRotate.Rotate_90;
							}
							if(itemVal == 180){
								pr = PRotate.Rotate_180;
							}
							if(itemVal == 270){
								pr = PRotate.Rotate_270;	
							}
							
						}
						if (item.opt("tab") != null) {
							String itemVal = item.getString("tab");
							int tab = Integer.valueOf(itemVal);
							for (int s = 0; s < tab; s++) {
								xoffset += "	";
							}
						}
						if (item.opt("rowSpan") != null) {
							String itemVal = item.getString("rowSpan");
							int value = Integer.valueOf(itemVal);
							byte[] data = new byte[3];
							data[0] = 0x1b;
							data[1] = 0x33;
							data[2] = (byte) value;
							mPrinter.sendBytesData(data);
						}
						if (item.opt("columnSpan") != null) {
							String itemVal = item.getString("columnSpan");
							int value = Integer.valueOf(itemVal);
							byte[] data = new byte[3];
							data[0] = 0x1b;
							data[1] = 0x20;
							data[2] = (byte) value;
							mPrinter.sendBytesData(data);

						}
						mPrinter.setFont(0,xsize,ysize,isBold?1:0,isUnderLine?1:0);//设置字体，倍高，倍宽，加粗，下划线
						mPrinter.setPrinter(Command.ALIGN, Command. ALIGN_LEFT);//设置字体左对齐
						mPrinter.setLeftMargin(67);//新增设置左边距
						mPrinter.printText(content);//打印print Test!
						mPrinter.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 2);
					
					}
					
					
					if (key.equalsIgnoreCase("string2")) {
						String content = null;
						int xsize = 0;
						int ysize = 0;
						boolean isBold = false;
						boolean isUnderLine = false;
						PRotate pr = PRotate.Rotate_0;
						String xoffset = "";
						LableFontSize size = LableFontSize.Size_16;

						if (item.opt("content") != null) {
							content = item.getString("content");
						}
						Log.e("print", "string:" + content);

						if (item.opt("xsize") != null) {
							xsize = (int) item.getDouble("xsize");
							
						}
						if (item.opt("ysize") != null) {
							ysize = (int) item.getDouble("ysize");
						
						}

						if (item.opt("bold") != null) {
							isBold = item.getBoolean("bold");
						}
						if (item.opt("underline") != null) {
							isUnderLine = item.getBoolean("underline");
						}

						if (item.opt("alignment") != null) {
							String itemVal = item.getString("alignment");
							if (itemVal.equals("left")) {

								
								
							}
							if (itemVal.equals("middle")) {
								
								
								
							}
							if (itemVal.equals("right")) {

								
								
							}
						}
						if (item.opt("angle") != null) {
							int  itemVal = item.getInt("angle");
							if(itemVal == 90){
								pr = PRotate.Rotate_90;
							}
							if(itemVal == 180){
								pr = PRotate.Rotate_180;
							}
							if(itemVal == 270){
								pr = PRotate.Rotate_270;	
							}
							
						}
						if (item.opt("tab") != null) {
							String itemVal = item.getString("tab");
							int tab = Integer.valueOf(itemVal);
							for (int s = 0; s < tab; s++) {
								xoffset += "	";
							}
						}
						if (item.opt("rowSpan") != null) {
							String itemVal = item.getString("rowSpan");
							int value = Integer.valueOf(itemVal);
							byte[] data = new byte[3];
							data[0] = 0x1b;
							data[1] = 0x33;
							data[2] = (byte) value;
							mPrinter.sendBytesData(data);
						}
						if (item.opt("columnSpan") != null) {
							String itemVal = item.getString("columnSpan");
							int value = Integer.valueOf(itemVal);
							byte[] data = new byte[3];
							data[0] = 0x1b;
							data[1] = 0x20;
							data[2] = (byte) value;
							mPrinter.sendBytesData(data);

						}
						mPrinter.setFont(0,xsize,ysize,isBold?1:0,isUnderLine?1:0);//设置字体，倍高，倍宽，加粗，下划线
						mPrinter.setPrinter(Command.ALIGN, Command. ALIGN_LEFT);//设置字体左对齐
						mPrinter.setLeftMargin(67);//新增设置左边距
						mPrinter.printText(content);//打印print Test!
						mPrinter.setPrinter(Command.PRINT_AND_WAKE_PAPER_BY_LINE, 2);
					
					
					}
					
					
					
					if (key.equalsIgnoreCase("barCode")) {
						String content = null;
						if (item.opt("content") != null) {
							content = item.getString("content");
						}
						int length = 2;
						if (item.opt("length") != null) {
							length = item.getInt("length");
						}
						int height = 50;
						if (item.opt("length") != null) {
							height = item.getInt("length");
						}
						Barcode barcode = new Barcode(BarcodeType.CODE128, length,
								height, 0, content);
						mPrinter.printBarCode(barcode);

					}
					if (key.equalsIgnoreCase("2DbarCode")) {
						String content = null;
						if (item.opt("content") != null) {
							content = item.getString("content");
						}
						int length = 150;
						if (item.opt("length") != null) {
							length = item.getInt("length");
						}
						int left = 50;
						if (item.opt("left") != null) {
							left = item.getInt("left");
						}
						mPrinter.setLeftMargin(left);

						Matrix matrix = new Matrix();
						matrix.postScale(1f, 1f);

						Bitmap resizedBitmap = Bitmap.createBitmap(
								createImage(content, length, length), 0, 0, length,
								length, matrix, true);

						mPrinter.printImage(resizedBitmap, PAlign.NONE,left,false);
					}
				}

			}
			return true;
			
		
		
	}

	// 生成QR图
	public static Bitmap createImage(String text, int QR_WIDTH, int QR_HEIGHT) {
		try {
			// 需要引入core包
			QRCodeWriter writer = new QRCodeWriter();

			Log.i(TAG, "生成的文本：" + text);
			if (text == null || "".equals(text) || text.length() < 1) {
				return null;
			}

			// 把输入的文本转为二维码
			BitMatrix martix = writer.encode(text, BarcodeFormat.QR_CODE,
					QR_WIDTH, QR_HEIGHT);

			System.out.println("w:" + martix.getWidth() + "h:"
					+ martix.getHeight());

			Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
			hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
			BitMatrix bitMatrix = new QRCodeWriter().encode(text,
					BarcodeFormat.QR_CODE, QR_WIDTH, QR_HEIGHT, hints);
			int[] pixels = new int[QR_WIDTH * QR_HEIGHT];
			for (int y = 0; y < QR_HEIGHT; y++) {
				for (int x = 0; x < QR_WIDTH; x++) {
					if (bitMatrix.get(x, y)) {
						pixels[y * QR_WIDTH + x] = 0xff000000;
					} else {
						pixels[y * QR_WIDTH + x] = 0xffffffff;
					}

				}
			}

			Bitmap bitmap = Bitmap.createBitmap(QR_WIDTH, QR_HEIGHT,
					Bitmap.Config.ARGB_8888);

			bitmap.setPixels(pixels, 0, QR_WIDTH, 0, 0, QR_WIDTH, QR_HEIGHT);

			return bitmap;

		} catch (WriterException e) {
			e.printStackTrace();
		}
		return null;
	}
}
